import 'package:event_bus/event_bus.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

typedef Widget SectionHeaderBuilder(BuildContext context, SectionItemList item, int sectionIndex, { double shrinkOffset, bool overlapsContent });
typedef Widget SectionItemBuilder(BuildContext context, dynamic data, int index, SectionItemList itemList);
typedef Widget SctionContainerBuilder(BuildContext context, Widget child);

class SectionItemList<T> {
  final String key;
  final String title;
  final List<T> list;
  

  SectionItemList({ 
    this.key, 
    @required this.title, 
    @required this.list,
  });
}

class SectionListView extends StatefulWidget {
  SectionListView({
    Key key, 
    @required this.renderSectionItem, 
    @required this.renderSectionHeader, 
    @required this.data,
    this.headerHeight = 30,
    this.renderSectionContainer,
    this.controller,
  }) : super(key: key);

  final List<SectionItemList> data;
  final SectionItemBuilder renderSectionItem;
  final SectionHeaderBuilder renderSectionHeader;
  final SctionContainerBuilder renderSectionContainer;
  final double headerHeight;
  final ScrollController controller;

  _SectionListViewState createState() => _SectionListViewState();
}

class _SectionListViewState extends State<SectionListView> {
  @override
  Widget build(BuildContext context) {
    List<Widget> slivers = <Widget>[];
    int index = 0;
    for (SectionItemList itemList in widget.data) {
      if(itemList.list.length<=0) continue;
      slivers.add(
        SliverSectionHeader(
          index: index,
          delegate: SectionHeaderDelegate(
            (BuildContext context, double shrinkOffset, bool overlapsContent,dynamic data, int _index) {
              if(overlapsContent) {
                eventBus.fire(_index);
              }
              return widget.renderSectionHeader(context, data, _index, shrinkOffset: shrinkOffset, overlapsContent: overlapsContent);
            },
            headerHeight: widget.headerHeight,
            index: index,
            data: itemList,
          ),
        )
      );
      slivers.add(
        SliverList(
          delegate: SliverChildBuilderDelegate(
            (BuildContext context, int i) => widget.renderSectionItem(context, itemList.list.elementAt(i), i, itemList), 
            childCount: itemList.list.length
          ),
        )
      ); 
      index++;
    }

    return CustomScrollView(
       physics: ClampingScrollPhysics(),
       controller: widget.controller,
       slivers: slivers,
    );
  }
}


typedef SectionHeaderDelegateBuilder(BuildContext context, double shrinkOffset, bool overlapsContent, dynamic data, int index );

class SectionHeaderDelegate extends SliverPersistentHeaderDelegate {
  final SectionHeaderDelegateBuilder builder;
  final double headerHeight;
  final TickerProvider provider;
  final int index;
  final dynamic data;

  SectionHeaderDelegate(this.builder, { this.provider, this.headerHeight = 30, this.data, this.index });

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return builder(context, shrinkOffset, overlapsContent, data, index, );
  }

  @override
  double get maxExtent => headerHeight;

  @override
  double get minExtent => headerHeight;

  FloatingHeaderSnapConfiguration get snapConfiguration {
    if(this.provider != null) {
      return FloatingHeaderSnapConfiguration(vsync: provider,);
    }
    return null;
  }

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return true;
  }

}


EventBus eventBus = EventBus();

class SliverSectionHeader extends StatefulWidget {
  SliverSectionHeader({Key key, this.delegate, this.index}) : super(key: key);

  final SliverPersistentHeaderDelegate delegate;
  final int index;

  _SliverSectionHeaderState createState() => _SliverSectionHeaderState();
}

class _SliverSectionHeaderState extends State<SliverSectionHeader> {
  int overlapsContentIndex;

  @override
  void initState() { 
    super.initState();
    eventBus.on<int>().listen((int index) {
      overlapsContentIndex = index;
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    return SliverPersistentHeader(
       delegate: widget.delegate,
      //  pinned: overlapsContentIndex == null ? true : overlapsContentIndex<=widget.index,
    );
  }
}